package com.robot.console.util;

/**
 * A Thread Pool API.
 * 
 * Tasks that wish to get run by the thread pool must implement the
 * java.lang.Runnable interface. Such tasks are placed in the pool via the
 * add()method. Usage:
 * 
 * <pre>
 * // Create a pool with 5 threads.
 * ThreadPool pool = new ThreadPool(5);
 * Start the pool
 * pool.start();
 * // Add an entry to be &quot;run&quot; by the pool.
 * pool.add(new Worker());
 * // The following object will be &quot;run&quot; by the thread pool
 * // beginning in the run() method.
 * class Worker implements Runnable {
 *      public void run() {
 *              . . .
 *      }
 * }
 * <p>
 * Title: 123 Flash Chat Server
 * </p>
 * <p>
 * Description: 123 Flash Chat Server Standard Version
 * </p>
 * <p>
 * Copyright: Copyright (c) 2003 - 2005
 * </p>
 * <p>
 * Company: TopCMM
 * </p>
 * &#064;author Daniel Jiang
 * &#064;version 4.5
 * 
 */
public class ThreadPool
{
	private Thread[] pool;
	private WorkQueue workQueue;
	public static final int DEFAULT_SIZE = 20;
	private volatile boolean shouldRun;
	private boolean started;

	/**
	 * Create a default size thread pool.
	 */
	public ThreadPool()
	{
		this(DEFAULT_SIZE);
	}

	/**
	 * Create a thread pool.
	 * 
	 * @arg int size - The number of threads initially created.
	 */
	public ThreadPool(int size)
	{
		if (size < 1)
		{
			throw new IllegalArgumentException();
		}
		workQueue = new WorkQueue();
		pool = new WorkerThread[size];
		shouldRun = true;
		started = false;
	}

	/**
	 * Starts the thread pool running. Each thread in the pool waits for work to
	 * be added using the add() method.
	 */
	public void startPool()
	{
		if (!started)
		{
			started = true;
			for (int i = 0; i < pool.length; i++)
			{
				pool[i] = new WorkerThread("Thread Pool: " + new Integer(i).toString());
				pool[i].start();
			}
		}
	}

	/**
	 * Stop the pool.
	 */
	public void stopPool()
	{
		shouldRun = false;
	}

	/**
	 * Add work to the queue.
	 * 
	 * @arg Runnable task - the task that is to be run.
	 */
	public void add(Runnable task)
	{
		workQueue.addWork(task);
	}

	/**
	 * inner class that does all the work
	 */
	private class WorkerThread extends Thread
	{
		private WorkerThread(String name)
		{
			setName(name);
		}

		public void run()
		{
			while (shouldRun)
			{
				try
				{
					Runnable work = (Runnable) workQueue.getWork();
					work.run();
				}
				catch (InterruptedException ie)
				{
					shouldRun = false;
				}
				/*
				 * try { sleep(100); } catch (InterruptedException ex) { }
				 */
			}
		}
	}
}
